Skip to content

Add CheaperInference provider - #7010

Open
aiapienthusiast wants to merge 21 commits into
anomalyco:devfrom
aiapienthusiast:cheaperinference-provider
Open

aiapienthusiast wants to merge 21 commits into
anomalyco:devfrom
aiapienthusiast:cheaperinference-provider

Conversation

@aiapienthusiast

@aiapienthusiast aiapienthusiast commented Sep 13, 2026

Copy link
Copy Markdown

Cheaper Inference is an OpenAI-compatible gateway. It serves each request from one of several providers for the requested model. The ranking field selects discount, speed or a balance of both, with balance as the default. The price is at or below the model maker's list price.

What this adds

providers/cheaperinference/ with provider.toml, logo.svg and 58 models. Each model is base_model-ed against the existing lab entry. Each one carries only cost, reasoning_options and limit deltas. The change adds no file under the top-level models/.

The 58 models are every chat model the gateway serves: openai 14, anthropic 13, zhipuai 9, google 8, deepseek 5, alibaba 5, and one each from xai, moonshotai, minimax and meta. The image-generation and video routes stay out.

Rates

The rates come from GET /v1/models, read at 2026-09-16T08:00:58Z, pricing_version sha256:1099de72…. Cache rates are included.

Four OpenAI models price a second band above 272k input tokens. The files record it as [[cost.tiers]]: gpt-6-astra, gpt-5.6-sol, gpt-5.6-terra and gpt-5.6-luna.

The gateway reprices often, so these rates are a timestamped snapshot. The first two comment lines of each file carry the source, the pricing_version and the discount off the maker's list price.

Reasoning options

reasoning_options come from the lab entries. 51 of the 58 models have them.

toggle is set on the 13 models where a live request confirms that the gateway forwards it. Each file carries a wire comment that names the exact field:

  • {"reasoning": {"enabled": false}} on POST /v1/chat/completions for 12 models;
  • {"thinking": {"type": "disabled"}} for glm-4.5-air, which ignores the first form.

In each case the disabled form returns no reasoning content, and the enabled form returns it.

claude-sonnet-5 and qwen-3-8-max keep their other reasoning options, but no toggle. reasoning.enabled changed nothing in the reply.

gemini-2.5-flash and glm-4.6 carry no reasoning options. The gateway reports no reasoning for them, although their lab entries have a toggle.

Limits

limit.output is set for every model, from the gateway's declared maximum. limit.context is set only where the gateway's declared window differs from the lab entry (23 models).

Daily sync

The provider is wired into the daily sync, so the snapshot does not go stale:

  • packages/core/src/sync/providers/cheaperinference.ts reads the same /v1/models endpoint. It reuses factorBaseModel from the OpenRouter module, so every entry stays base_model-ed.
  • packages/core/src/sync/index.ts registers the provider in the aggregators group.
  • .github/workflows/sync-models.yml passes a CHEAPERINFERENCE_API_KEY secret.

The endpoint needs a key to answer, so the sync run is a no-op until that secret exists. Nothing else in the workflow changes.

Checks

packages/core/test/cheaperinference.test.ts covers the module with 6 tests. They pass.

bun validate passes on the full tree.

CheaperInference is an OpenAI-compatible gateway that serves each request
from one of several providers for the requested model, ranked by discount,
speed or a balance of both, at or below the model maker's list price. Adds the
provider entry plus 16 relayed models, all using base_model against existing
lab metadata with provider-side cost, cache rates, long-context tiers and
reasoning_options only.

Rates come from GET /v1/models (pricing_version sha256:d7fdd65d…, checked
2026-09-13T10:00:38Z).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/cheaperinference/models/claude-sonnet-5.toml:98 - Check: Every toggle must have a leading top-of-file wire comment with the exact request path. Why: This multi-model OpenAI-compatible gateway adds toggle on five models (claude-sonnet-5, deepseek-v4-flash-0731, deepseek-v4.1-flash, kimi-k3, qwen-3-8-max) with only pricing comments above the first key. Callers and the catalog cannot tell which field turns reasoning on/off on this host (e.g. thinking.type, enable_thinking, reasoning.enabled). Action: Add a leading # Toggle: … (and matching effort wire path if applicable) on each of those five files documenting this host’s real control, or drop toggle if the gateway does not expose a separate on/off control.

The gateway documents that the reasoning field is forwarded to the serving
provider but names no on/off control of its own, so only the effort levels
inherited from the lab entries are authored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [possible mistake] providers/cheaperinference/models/claude-sonnet-5.toml:5 - Check: Relay reasoning_options must match lab + same-surface peers for controls this host actually forwards. Why: Patch 2 removed toggle on claude-sonnet-5, both DeepSeek Flash models, kimi-k3, and qwen-3-8-max while stating the gateway forwards reasoning to the upstream provider. Lab/OpenRouter baselines for those models use a separate on/off control plus graded effort (no none in effort). Effort-only leaves no documented off path and understates capability if thinking / enable_thinking / equivalent fields pass through. Action: Either restore toggle (with a leading wire-path comment) on those five models to match lab/peers, or cite host docs/tests showing on/off fields are stripped or rejected and keep effort-only.
  • [medium] [possible mistake] providers/cheaperinference/models/deepseek-v4-flash-0731.toml:17 - Check: Provider [limit] overrides must be real host deltas from the catalog API, not copy-paste caps. Why: Lab deepseek-v4-flash-0731 output is 384_000, but this file sets output = 65536 while sibling deepseek-v4.1-flash only bumps context and still inherits 384_000 output. That split is inconsistent for one gateway and matches common 64k defaults more than the lab Flash ceiling. Action: Confirm both DeepSeek limits from GET /v1/models (or equivalent) and align output/context with what the host actually serves; drop non-delta overrides.
  • [low] [possible mistake] providers/cheaperinference/provider.toml:1 - Check: Rich provider catalog APIs should get a sync module when they can authoritatively drive model/pricing data. Why: The PR already keys rates off versioned GET /v1/models (pricing_version), so hand-maintained costs/limits will drift. Action: Add a sync module per sync.md, or note in the PR why this catalog stays hand-authored.

aiapienthusiast and others added 2 commits September 13, 2026 17:19
Tested on the live chat completions endpoint: reasoning.enabled = false
removes reasoning tokens and the reasoning field on kimi-k3, qwen-3-8-max,
deepseek-v4.1-flash and deepseek-v4-flash-0731, and true restores them, so
those four carry toggle with the wire path as a leading comment. On
claude-sonnet-5 neither reasoning.enabled nor thinking had any observable
effect on this path, so it stays effort-only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Registers a sync module for the CheaperInference provider so the hourly
workflow keeps its rates current instead of leaving them to drift.

The gateway's catalog endpoint is authoritative for pricing: exact per-million
input, output, cache-read and cache-write rates, an above_threshold band with
its own token threshold for models priced in two bands, and the limits this
host actually serves. It exposes no reasoning controls, so the module sets
skipCreates and refuses to sync a reasoning model whose reasoning_options were
not hand-authored; image and video routes are skipped because their per-unit
media pricing cannot be expressed by the cost schema.

Reading the catalog needs a key, so the workflow gains a
CHEAPERINFERENCE_API_KEY secret. The endpoint accepts a key restricted to
read-only scope, which cannot spend from the account behind it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@aiapienthusiast

Copy link
Copy Markdown
Author

Addressed all three.

  1. toggle: tested on the live /v1/chat/completions. reasoning: {enabled: false} removes reasoning tokens and the reasoning field on kimi-k3, qwen-3-8-max, deepseek-v4.1-flash and deepseek-v4-flash-0731, and enabled: true restores them (kimi-k3: 26 reasoning tokens → 0 → 26). Those four now carry toggle with # Toggle: reasoning.enabled = true|false as a leading comment. On claude-sonnet-5 neither reasoning.enabled nor thinking had any observable effect on this path, so it stays effort-only.
  2. DeepSeek limits: both come from GET /v1/models. deepseek-v4-flash-0731 returns context_length: 1048576, max_output_tokens: 65536; deepseek-v4.1-flash returns context_length: 1048576, max_output_tokens: 384000. Hence 0731 overrides both and 4.1-flash only context.
  3. Sync module: added to this PR (packages/core/src/sync/providers/cheaperinference.ts with tests, registration in sync/index.ts, and a CHEAPERINFERENCE_API_KEY line in the workflow). It only reads GET /v1/models, so a read-only key works; without the secret the matrix job for this provider fails the same way other keyed providers do. Replaying the live catalog through bun models:sync cheaperinference --dry-run gives 0 created, 0 updated, 0 removed, 16 unchanged against the files in this PR.

@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Sep 13, 2026
@github-actions github-actions Bot removed the reviewer: ready Automated review found no actionable items label Sep 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/cheaperinference/models/claude-haiku-4.5.toml:5 - Check: reasoning = true models must keep reasoning and author host reasoning_options from lab/peers. Why: Lab models/anthropic/claude-haiku-4-5 and first-party Anthropic both mark this as a reasoner (budget_tokens); OpenRouter peers use toggle. Setting reasoning = false drops required controls and mislabels the model. Same error on claude-opus-4.7.toml, claude-opus-4-8-fast.toml, gemini-2.5-flash.toml, gemini-3.5-flash.toml, gemini-3.1-flash-lite.toml, and glm-4.6.toml. Action: Remove the false overrides; set reasoning_options from lab + same-surface peers for each model (and restore reasoning = true by inheritance).
  • [high] [violation] providers/cheaperinference/models/claude-sonnet-5.toml:7 - Check: Every toggle needs a leading top-of-file wire-path comment. Why: Final files keep type = "toggle" but drop the # Toggle: … header (including after the earlier live-test comments). Sync strips mid-file comments, so callers cannot learn the control. Affected: claude-sonnet-5, deepseek-v4.1-flash, deepseek-v4-pro-0813, kimi-k3, qwen-3-8-max, qwen3-5-35b-a3b, qwen3-6-35b-a3b, qwen3.6-27b, glm-4.5, glm-4.5-air, glm-4.7, glm-5, glm-5.1. Action: Add a leading # Toggle: <exact request field> on each toggle file, or remove toggle where this host does not expose on/off.
  • [high] [violation] providers/cheaperinference/models/minimax-m2.7.toml:6 - Check: Relay effort must match lab/peer baseline, not invent graded levels. Why: First-party MiniMax and OpenRouter both use reasoning_options = [] (always-on, no caller control). values = ["high"] invents a control this model family does not expose. Action: Change to reasoning_options = [].
  • [high] [violation] providers/cheaperinference/models/claude-sonnet-4.5.toml:8 - Check: Do not invent budget_tokens on an OpenAI chat-completions relay unless this host has a real reasoning-budget field. Why: CheaperInference is an OpenAI-compatible gateway. Native Anthropic Messages budget is a different surface; OpenRouter’s same-model OpenAI-style peer is toggle-only, not budget. Copying bare budget_tokens (also on claude-opus-4.5, claude-opus-4.6, claude-sonnet-4.6) misstates the API. Action: Drop budget_tokens unless you document the exact gateway budget wire path; align Claude options with this host’s chat-completions controls and established OpenAI-compat peers.
  • [medium] [possible mistake] providers/cheaperinference/models/gpt-5.6-luna.toml:16 - Check: Context tier size is the band start and should match lab/peer convention. Why: OpenAI and peers use 272_000; the new sync helper also normalizes gateway thresholds to 272_000. Hand files now use 271_999 on luna/sol/terra, so catalog semantics disagree with every peer and with the next sync rewrite. Action: Use 272_000 (or make hand files match whatever buildTiers emits) and keep TOML + sync consistent.
  • [medium] [possible mistake] providers/cheaperinference/models/deepseek-v4-flash.toml:7 - Check: DeepSeek relay effort/toggle should follow lab + same-surface peers for that ID. Why: First-party Flash/Pro use toggle + graded effort without none (high/max or low/high/max). These entries use none/high/xhigh (and 0731 uses none/low/high/max with no toggle), which matches some third-party peers but conflicts with the lab baseline and earlier live-test toggle evidence on this host. Action: Verify on this gateway and align each DeepSeek ID to either lab shape (toggle + real levels, with wire comment) or a documented peer shape—do not mix none and toggle, and do not drop a working toggle without re-test notes.

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/cheaperinference/models/glm-4.5-air.toml:3 - Check: reasoning = true requires reasoning_options. Why: After removing toggle, this file has no reasoning_options while base_model inherits reasoning = true from zhipuai/glm-4.5-air (lab/ZAI use toggle-only). Resolved model will fail the reasoning-options requirement. Action: Restore a host-accurate control set (lab/ZAI baseline is toggle with a leading wire comment if forwarded) or set reasoning_options = [] only with affirmative evidence of no caller control.
  • [high] [violation] providers/cheaperinference/models/deepseek-v4-flash.toml:11 - Check: toggle must not pair with effort that includes none. Why: Final options are toggle + ["none", "high", "xhigh"], which is an explicit dual-off shape. Lab DeepSeek Flash is toggle + low/high/max; OpenRouter peers use toggle + high/xhigh without none. Action: Pick one off mechanism: either toggle + graded effort without none (lab/peer set), or effort-only with none and no toggle; drop invented levels.
  • [high] [violation] providers/cheaperinference/models/deepseek-v4-pro.toml:11 - Check: Same toggle/none rule and DeepSeek baseline. Why: Same illegal toggle + ["none", "high", "xhigh"]. Lab Pro is toggle + high/max (no none, no xhigh). Action: Align to lab/peer shape: toggle + ["high", "max"] (or this host’s verified equivalent without combining toggle and none).
  • [high] [violation] providers/cheaperinference/models/claude-haiku-4-5.toml:5 - Check: Do not mark lab reasoners as non-reasoning without host proof. Why: reasoning = false overrides lab/Anthropic Haiku 4.5 (reasoning = true, first-party budget_tokens). That drops required controls and mislabels a reasoner. Action: Remove reasoning = false and author this host’s real controls (or [] only if live requests prove no control).
  • [high] [violation] providers/cheaperinference/models/claude-opus-4-7.toml:6 - Check: Same reasoning override rule. Why: Lab/Anthropic Opus 4.7 is reasoning = true with effort low/medium/high/xhigh/max; this file forces reasoning = false. Action: Drop the false override and set reasoning_options from lab/same-surface peers for this gateway path.
  • [high] [violation] providers/cheaperinference/models/claude-opus-4-8-fast.toml:6 - Check: Fast alias of a reasoner still needs accurate reasoning metadata. Why: base_model = "anthropic/claude-opus-4-8" is a reasoner; reasoning = false erases that without evidence that the fast route disables thinking. Action: Keep reasoning on unless proven off; author Opus 4.8 effort (and any host-specific delta) instead of reasoning = false.
  • [high] [violation] providers/cheaperinference/models/gemini-2.5-flash.toml:5 - Check: Relay of a reasoner must not set reasoning = false from uncertainty. Why: Lab/Google Gemini 2.5 Flash is reasoning = true with toggle + budget_tokens. Action: Remove reasoning = false and copy the intersection this OpenAI-compatible path actually exposes.
  • [high] [violation] providers/cheaperinference/models/gemini-3.5-flash.toml:5 - Check: Same Gemini reasoner rule. Why: Lab/Google use effort minimal/low/medium/high; this file sets reasoning = false. Action: Restore reasoning + matching reasoning_options (or document live proof of no control and use []).
  • [high] [violation] providers/cheaperinference/models/gemini-3.1-flash-lite.toml:5 - Check: Same Gemini reasoner rule. Why: Lab/Google are reasoning with the same effort set; override is reasoning = false. Action: Fix like the other Gemini reasoners above.
  • [high] [violation] providers/cheaperinference/models/glm-4.6.toml:5 - Check: Same for GLM reasoners. Why: Lab/ZAI GLM-4.6 is reasoning = true with toggle; this file sets reasoning = false and omits controls. Action: Remove the false override and author toggle (with wire comment) or verified [].
  • [high] [violation] providers/cheaperinference/models/minimax-m2.7.toml:6 - Check: Baseline = lab/peer option set; do not invent effort. Why: First-party MiniMax-M2.7 uses reasoning_options = [] (always-on / no caller control). This PR authors effort = ["high"] only. Action: Use reasoning_options = [] unless this host documents a real effort wire with meaningful effect.
  • [high] [possible mistake] providers/cheaperinference/models/claude-opus-4.5.toml:12 - Check: Do not treat Anthropic Messages controls as interchangeable with this OpenAI chat-completions gateway. Why: Files add bare budget_tokens (and sometimes effort) for Claude 4.5/4.6 family models. Native Anthropic uses Messages thinking.budget_tokens; same-surface OpenAI-compat peers (e.g. OpenRouter) often expose reasoning.enabled toggle / effort, not Anthropic budget. No leading wire comment proves a real budget field on CheaperInference. Action: For each Claude entry, author only controls verified on this host (wire path in a top comment); drop budget_tokens unless a reasoning-budget field is confirmed.
  • [high] [possible mistake] providers/cheaperinference/models/claude-sonnet-4.5.toml:8 - Check: Same Anthropic surface / budget rule. Why: Sonnet 4.5 is budget-only here; OpenRouter peer is toggle-only on the OpenAI-compat path. Action: Replace with host-verified options (likely toggle and/or effort), not assumed Messages budget.
  • [high] [possible mistake] providers/cheaperinference/models/claude-opus-4.6.toml:12 - Check: Same Anthropic surface / budget rule. Why: effort + bare budget_tokens without a CheaperInference wire comment. Action: Verify and keep only forwarded controls; add leading comments for any retained toggle/budget path.
  • [high] [possible mistake] providers/cheaperinference/models/claude-sonnet-4.6.toml:12 - Check: Same Anthropic surface / budget rule. Why: Same effort + budget_tokens pattern without host wire evidence. Action: Same fix as Opus/Sonnet 4.6 peers above.
  • [medium] [violation] providers/cheaperinference/models/deepseek-v4-flash-0731.toml:6 - Check: DeepSeek V4 relay baseline is toggle + graded effort, not invented none alone. Why: Final shape is effort ["none", "low", "high", "max"] with no toggle. Lab/OpenRouter-style peers for this ID use toggle + low/high/max (no none). Earlier commits claimed reasoning.enabled worked, then dropped toggle. Action: Restore toggle + lab effort without none, or keep effort-with-none only if live requests show off is effort=none and not a separate toggle.
  • [medium] [violation] providers/cheaperinference/models/gpt-5.6-luna.toml:16 - Check: Context tier size is where the higher band starts; match OpenAI/sync normalization. Why: Hand files use size = 271_999 while OpenAI lab tiers and this PR’s own sync (threshold + 1, then round) target 272_000. 271_999 is the last base-rate token, not the band start, and the next sync would rewrite it. Action: Set [[cost.tiers]] size to 272_000 on luna/sol/terra (and keep sync/hand output consistent).
  • [medium] [possible mistake] providers/cheaperinference/models/qwen-3-8-max.toml:8 - Check: Qwen baseline is toggle + effort (+ budget only if this path has thinking_budget). Why: Toggle was confirmed then removed; bare budget_tokens remains without a wire comment. Lab Alibaba uses enable_thinking + effort + thinking_budget on its own API—not automatically on every OpenAI-compat relay. Action: Re-verify on this host: restore toggle with a leading wire comment if it works; keep budget_tokens only if a real reasoning-budget field is forwarded; otherwise drop budget.
  • [medium] [possible mistake] providers/cheaperinference/models/qwen3-5-35b-a3b.toml:8 - Check: budget_tokens only for real reasoning budgets on this path. Why: Toggle is documented, but bare budget_tokens has no wire comment and may be copied from Alibaba chat APIs rather than proven on CheaperInference. Action: Confirm thinking_budget (or equivalent) on this gateway; add a leading budget wire comment or remove budget_tokens.
  • [low] [possible mistake] providers/cheaperinference/models/gpt-5.6-luna.toml:13 - Check: Material pricing/tier claims need reviewable evidence. Why: Costs and long-context bands are material catalog facts; the body cites GET /v1/models but no public doc mapping of the threshold semantics. Action: In the PR body, briefly map each contested field (cache rates, 272k band start, discounts) to the catalog field names returned by the API.

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/cheaperinference/models/claude-haiku-4.5.toml:5 - Check: reasoning = true models must keep reasoning capability and host-appropriate reasoning_options. Why: Lab anthropic/claude-haiku-4-5, first-party Anthropic, and OpenRouter all treat Haiku 4.5 as a reasoner (budget/toggle). Setting reasoning = false with no controls understates capability on this relay. Action: Remove reasoning = false and author options matching this host’s real surface (lab/peers: budget and/or toggle), with a leading toggle wire comment if toggle is used.
  • [high] [violation] providers/cheaperinference/models/claude-opus-4.7.toml:5 - Check: Do not disable reasoning on models that reason on the lab and peers. Why: Lab and providers/anthropic / OpenRouter mark Opus 4.7 as reasoning with effort low|medium|high|xhigh|max (plus toggle on relays). reasoning = false is incorrect. Action: Drop reasoning = false and set reasoning_options to the lab/peer effort set this gateway actually forwards.
  • [high] [violation] providers/cheaperinference/models/claude-opus-4-8-fast.toml:5 - Check: Fast/priced variants still inherit the base model’s reasoning unless the host truly strips it. Why: base_model = "anthropic/claude-opus-4-8" is a reasoner (effort L/M/H/xhigh/max); OpenRouter peers keep reasoning. reasoning = false is unsupported. Action: Remove reasoning = false and author the Opus 4.8 effort (and toggle only if this host forwards it).
  • [high] [violation] providers/cheaperinference/models/gemini-2.5-flash.toml:5 - Check: Relay must not invent reasoning = false against lab/first-party/peer baselines. Why: Lab and Google first-party mark Gemini 2.5 Flash as reasoning (toggle + budget_tokens); OpenRouter keeps a toggle. Action: Restore reasoning and copy the controls this OpenAI-compatible path actually exposes (at least peer toggle; budget only if a real reasoning budget field exists).
  • [high] [violation] providers/cheaperinference/models/gemini-3-5-flash.toml:5 - Check: Reasoning capability must match lab + first-party + peers. Why: Lab/Google/OpenRouter all treat Gemini 3.5 Flash as reasoning with effort minimal|low|medium|high. Action: Remove reasoning = false and set that effort list (or the verified subset this host accepts).
  • [high] [violation] providers/cheaperinference/models/gemini-3.1-flash-lite.toml:5 - Check: Same reasoning baseline rule. Why: Lab/Google/OpenRouter mark Gemini 3.1 Flash Lite as reasoning with effort (and toggle on OpenRouter). Action: Remove reasoning = false and author matching reasoning_options.
  • [high] [violation] providers/cheaperinference/models/glm-4.6.toml:5 - Check: GLM-4.6 is a reasoner with a real on/off control. Why: Lab and Zhipu first-party set reasoning = true with toggle; this file forces reasoning = false and omits options. Action: Remove reasoning = false and add toggle with a leading wire-path comment if the gateway forwards it (else document the verified control).
  • [high] [violation] providers/cheaperinference/models/deepseek-v4-flash.toml:8 - Check: Never pair toggle with effort that already includes none. Why: Final options are toggle + ["none", "high", "xhigh"], which is an invalid dual off control. Lab/OpenRouter baselines are toggle + graded effort without none (OpenRouter: high|xhigh; DeepSeek first-party alias: low|high|max). Action: Pick one off mechanism: either toggle + graded values without none, or effort-only including none—matching the verified host wire form.
  • [high] [violation] providers/cheaperinference/models/deepseek-v4-pro.toml:8 - Check: Same toggle vs none rule. Why: Same invalid toggle + none|high|xhigh shape; first-party V4 Pro is toggle + high|max, OpenRouter peer is toggle + high|xhigh (no none). Action: Remove the dual off; align effort values to lab/peer + live host behavior.
  • [high] [violation] providers/cheaperinference/models/deepseek-v4-flash-0731.toml:6 - Check: Relay effort set must follow lab/peer baseline, not invent none. Why: Authored ["none", "low", "high", "max"] with no toggle. OpenRouter and the DeepSeek V4 flash family use toggle + low|high|max (no none). Action: Match peers: toggle (with leading # Toggle: … wire comment) + ["low", "high", "max"], or prove this host’s distinct wire form.
  • [high] [violation] providers/cheaperinference/models/minimax-m2.7.toml:5 - Check: Do not invent effort levels when lab/peers expose no caller control. Why: MiniMax first-party and OpenRouter set reasoning_options = [] (always-on). This file invents effort = ["high"]. Action: Use reasoning_options = [] unless you have host docs/live proof of a real effort control.
  • [high] [violation] providers/cheaperinference/models/claude-opus-4.5.toml:12 - Check: Do not treat Anthropic Messages controls as interchangeable with this OpenAI-compatible surface; no invented budget_tokens. Why: This host is an OpenAI-compatible gateway. OpenRouter’s same-model peer is toggle-only; Anthropic first-party budget is Messages extended-thinking. Authoring bare budget_tokens (and effort) without a verified reasoning-budget field on this path is invalid. Action: Drop budget_tokens unless the gateway documents a real reasoning budget; copy the openai-compat peer shape (typically toggle and/or effort only).
  • [high] [violation] providers/cheaperinference/models/claude-sonnet-4.5.toml:7 - Check: Same Anthropic-vs-OpenAI-compat control-surface rule. Why: File is budget-only. OpenRouter Sonnet 4.5 is toggle-only on the shared openai-compat style path; native Anthropic budget is a different API. Action: Replace with the controls this host actually forwards (likely toggle and/or effort), not Messages budget_tokens by default.
  • [medium] [violation] providers/cheaperinference/models/claude-opus-4.6.toml:12 - Check: budget_tokens only when this host has a real reasoning-budget field. Why: Opus 4.6 still has native budget on Anthropic Messages, but this provider is openai-compatible; peers on similar relays often use toggle+effort, and Claude 4.7+ policy already rejects budget inventing. Action: Keep effort (and toggle if forwarded); include budget_tokens only with a verified wire path on CheaperInference.
  • [medium] [violation] providers/cheaperinference/models/claude-sonnet-4.6.toml:12 - Check: Same budget rule on openai-compat Claude routes. Why: budget_tokens is copied from Anthropic Messages while OpenRouter Sonnet 4.6 is toggle+effort without budget. Action: Align to this host’s verified surface; remove budget unless proven.
  • [medium] [violation] providers/cheaperinference/models/qwen-3-8-max.toml:14 - Check: budget_tokens requires a real reasoning-budget field on this host. Why: Alibaba uses thinking_budget / enable_thinking; this gateway’s documented/tested control in the PR history is reasoning.enabled. Bare budget_tokens without a confirmed budget wire path invents a control. Action: Keep effort (and restore toggle if still forwarded); add budget_tokens only with a leading budget wire comment and live/docs evidence.
  • [medium] [violation] providers/cheaperinference/models/gpt-5.6-luna.toml:16 - Check: Context tier size is the band start threshold; stay consistent with lab/sync. Why: Files use 271_999 while OpenAI lab tiers and this PR’s own sync normalizer target 272_000 (threshold + 1 then round). Next sync would rewrite tiers and the band semantics disagree with catalog convention. Action: Use 272_000 (or whatever single normalized boundary the sync module emits) on luna/sol/terra; keep the sync test and TOMLs aligned.
  • [medium] [possible mistake] providers/cheaperinference/models/qwen-3-8-max.toml:8 - Check: Toggle must be kept when this host was shown to forward on/off. Why: Earlier commits claimed live reasoning.enabled worked for qwen-3-8-max, then later removed toggle while keeping effort/budget. That contradicts the verified-forwarding rule and Alibaba’s hybrid baseline. Action: Re-verify once; if toggle still works, restore toggle + leading wire comment and drop any conflicting off-via-none.

aiapienthusiast and others added 2 commits September 16, 2026 21:30
Re-probed every model the review flagged on the live chat completions
endpoint, with a unique prompt per request so nothing came from a cache.

Reasoning comes back where the gateway catalog says it does not.
claude-opus-4-8-fast returns reasoning_content on every plain request
(7 of 7) and drops it for reasoning.enabled = false, and glm-4.6 returns
reasoning_content with 128 to 592 reasoning tokens for every graded effort
value. Both lose the reasoning = false line: opus-4-8-fast carries the
verified toggle plus the lab effort set, glm-4.6 the toggle its first-party
file also uses. gemini-3-5-flash reasons as well, and the gateway documents
its own set in a 400 - minimal, low, medium, high, thinking that cannot be
disabled - so it stays effort-only with those four values.

reasoning.enabled = false and reasoning.effort = none both switch reasoning
off on deepseek-v4-flash, deepseek-v4-pro and deepseek-v4-flash-0731, so
each keeps a single off control, the toggle, with graded values and no none:
high|xhigh, high|xhigh and low|high|max. minimax-m2.7 has a real toggle
(no reasoning in 4 of 4 requests with reasoning.enabled = false, reasoning
in every other form), so it replaces the empty options list.

The four Claude routes the review asked about - opus 4.5, opus 4.6, sonnet
4.5 and sonnet 4.6 - return no reasoning_content and no reasoning token
count at all, and effort, reasoning.enabled and thinking.budget_tokens are
each accepted with 200 and change nothing. budget_tokens goes, and
reasoning_options is empty rather than an effort list this host does not
honour. qwen-3-8-max, re-verified as the review asked: reasoning.enabled =
false no longer suppresses anything in 6 of 6 requests, so its toggle and
effort list go the same way.

The luna, sol and terra context tiers move from 271_999 to 272_000, the band
start the sync module emits and gpt-6-astra already carries.

claude-haiku-4.5, claude-opus-4.7, gemini-2.5-flash and gemini-3.1-flash-lite
keep reasoning = false: the catalog declares them non-reasoning and five wire
forms return nothing on each.

bun run validate passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
qwen3-5-35b-a3b, qwen3-6-35b-a3b and qwen3.6-27b carried budget_tokens, but
this gateway has no reasoning-budget field on the OpenAI-compatible path:
reasoning.max_tokens = 64 and thinking.budget_tokens = 64 are both accepted
with 200 and the reply still carries around a thousand characters of
reasoning, the same as a plain request.

Their toggles are re-verified and stay: reasoning.enabled = false returns no
reasoning content on all three, and true restores it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/cheaperinference/models/claude-opus-4.5.toml:6 - Check: reasoning_options = [] means the model reasons with no caller control. Why: Patch 09 states these Claude routes return no reasoning_content and no reasoning tokens under effort/toggle/budget, yet the files keep inherited reasoning = true with []. That misrepresents capability (always-on reasoner vs non-reasoning host). Same shape on claude-opus-4.6.toml, claude-sonnet-4.5.toml, claude-sonnet-4.6.toml, and qwen-3-8-max.toml. Action: If this host never emits reasoning, set reasoning = false and drop reasoning_options. If it does reason, drop [] and author the controls that actually change the wire response (lab/peer baseline), not an empty list.
  • [high] [possible mistake] providers/cheaperinference/models/claude-haiku-4.5.toml:5 - Check: Provider reasoning must reflect this host’s real behavior, not a catalog label alone. Why: Lab + first-party Anthropic mark Haiku 4.5 as reasoning (budget_tokens); this file forces reasoning = false. Same pattern on claude-opus-4.7.toml, gemini-2.5-flash.toml, and gemini-3.1-flash-lite.toml (lab/Google first-party are reasoners with effort or toggle+budget). Action: Re-verify with prompts that elicit thinking and the lab wire forms. If reasoning appears, remove reasoning = false and set matching reasoning_options; if it truly never reasons here, keep reasoning = false and cite the probe in the leading comment.
  • [medium] [possible mistake] providers/cheaperinference/models/claude-opus-4.5.toml:5 - Check: Override-only attachment must be a real host delta and stay consistent with modalities. Why: Many files set attachment = false while still inheriting multimodal modalities.input from lab bases (Claude image/pdf, GPT image, Gemini multimodal, Qwen vision). No PR evidence that this OpenAI-compatible path rejects attachments. Action: Drop attachment = false unless verified; if verified, also override [modalities] so input matches what the host actually accepts.
  • [medium] [possible mistake] providers/cheaperinference/models/claude-opus-4-8-fast.toml:9 - Check: Provider-only interleaved when this API returns a reasoning side channel. Why: Patch 09 reports reasoning_content on claude-opus-4-8-fast and glm-4.6 (and similar DeepSeek/GLM toggles). Lab/peer entries for those families set [interleaved] field = "reasoning_content", but none of the CheaperInference files do. Action: Add interleaved on every model where live replies include reasoning_content (or reasoning_details), and omit it only where that field is absent.
  • [medium] [possible mistake] providers/cheaperinference/models/qwen-3-8-27b.toml:6 - Check: Relay effort/toggle baseline from lab + same-surface peers. Why: Authored effort = ["none", "low", "medium", "xhigh"] with no toggle. OpenRouter’s same model is toggle + low/medium/xhigh (no none). Extra none and missing toggle need host-specific proof. Action: Align with the verified CheaperInference surface (toggle and/or exact effort values), and document the wire path if toggle stays.

Answers the third review round, all of it re-probed on the live endpoint with
a unique prompt per request.

reasoning = false replaces reasoning_options = [] on claude-opus-4.5,
claude-opus-4.6, claude-sonnet-4.5 and claude-sonnet-4.6: no request form -
plain, reasoning.enabled, reasoning.effort, thinking.budget_tokens - returns
reasoning_content or a reasoning token count on those routes, so an empty
options list would claim an always-on reasoner that is not there. The four
that already carried reasoning = false keep it and now cite the probe in a
leading comment. qwen-3-8-max keeps reasoning = true with an empty options
list, because it does return reasoning_content on every request and neither
the toggle nor effort = "none" suppresses it.

interleaved records the side channel where the reply carries one: 33 models
return reasoning_content, gemini-3-flash-preview returns reasoning_details,
and glm-4.7 returns its reasoning in a plain reasoning field, which the schema
covers as interleaved = true. The OpenAI-shaped routes count reasoning tokens
without exposing any content, so they carry no interleaved.

attachment is dropped on gemini-3-flash-preview and gemini-3.1-pro-preview,
which accept an image_url part; the other sixteen reject it (400, or every
upstream route failing) and now also override modalities.input to text only
so the two agree.

qwen-3-8-27b gets the toggle it actually forwards plus low|medium|xhigh and no
none. gpt-5.5-pro is responses-shaped: /v1/chat/completions returns 400 and
/v1/responses answers, where effort medium and high work.

bun run validate passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/cheaperinference.ts:839 - Check: Missing reasoning controls must use MissingReasoningOptionsError so the runner leaves the local file alone and can open a missing-model issue. Why: buildCheaperInferenceModel throws a generic Error when a resolved model reasons without authored reasoning_options. That fails the whole hourly cheaperinference sync job instead of skipping that ID and preserving the existing TOML (see packages/core/src/sync/index.ts and missing-reasoning-options.ts). Action: Throw MissingReasoningOptionsError(model.id, …) (and cover it in packages/core/test/cheaperinference.test.ts).
  • [medium] [possible mistake] providers/cheaperinference/models/gemini-3.6-flash.toml:1 - Check: Host-side interleaved must be set when this API returns a reasoning side channel. Why: Patch 11 added [interleaved] for many same-host reasoners (gemini-3.7-flash, gemini-3-5-flash, GLM/DeepSeek/etc.) after live probes, but gemini-3.6-flash still has only effort + cost. If replies include reasoning_content (or another field), clients will miss the side channel. Action: Re-probe this route; add the matching interleaved field (or a leading comment that no side channel is returned).
  • [medium] [possible mistake] providers/cheaperinference/models/muse-spark-1.2.toml:1 - Check: Same interleaved requirement for reasoners on this host. Why: muse-spark-1.2 is reasoning = true with effort controls but got no interleaved entry while dozens of peer reasoners did. Action: Re-probe; author interleaved if reasoning content is present, or document that only token counts are returned.
  • [medium] [possible mistake] providers/cheaperinference/models/claude-fable-5.toml:1 - Check: Attachment/modalities overrides must match this host’s vision surface. Why: Sibling Claude routes (claude-opus-5, claude-sonnet-5, claude-opus-4.8, …) override attachment = false and modalities.input = ["text"] after probes that rejected image_url, but claude-fable-5, claude-fable-5.1, and claude-opus-5-fast still inherit lab attachment = true / image+pdf modalities while already claiming reasoning side channels on this gateway. Action: Probe image input on those three IDs; if rejected like the other Claude routes, add the same attachment + [modalities] overrides (and keep interleaved only where content is returned).

@aiapienthusiast

Copy link
Copy Markdown
Author

Both review rounds are answered here, and every claim below is a live probe on /v1/chat/completions with a unique prompt per request, sampled repeatedly because the gateway picks an upstream per request and names it in provider (glm-4.6 alone came back from Z.AI, Venice and Novita). Fixes are in e71f1b5, dca50c0 and 6fdcfcb; bun run validate passes.

Reasoning: what this host actually returns

Nine models return nothing on any wire form I could find - plain, reasoning.enabled, reasoning.effort, top-level reasoning_effort, thinking = {type: "enabled", budget_tokens: N} - no reasoning_content, no reasoning_details, no reasoning token count in usage. For four of them (claude-haiku-4.5, claude-opus-4.7, gemini-2.5-flash, gemini-3.1-flash-lite) the catalog agrees and reports capabilities.reasoning: false. The other four (claude-opus-4.5, claude-opus-4.6, claude-sonnet-4.5, claude-sonnet-4.6) it reports as reasoning, and they were the ones carrying reasoning_options = []. You are right that an empty list claims an always-on reasoner, so those four now carry reasoning = false, and all nine cite the probe in a leading comment. claude-haiku-4.5 is the closest call: the reasoning_content key is present on every reply with the value null.

qwen-3-8-max is the opposite case and keeps reasoning = true with reasoning_options = []. reasoning_content comes back on every request, 76-369 characters and 23-139 reasoning tokens, and reasoning.enabled = false (6 of 6) and effort = "none" both leave it in place. That is a real always-on reasoner with no caller control, which is what the empty list says.

Three models the catalog reports as non-reasoning do reason, so reasoning = false came off them:

model live authored
claude-opus-4-8-fast reasoning_content on 7 of 7 plain requests (47-64 chars), gone for reasoning.enabled = false and for effort = "none" toggle + effort low, medium, high, xhigh, max, the providers/anthropic set, no none
gemini-3-5-flash reasoning_content plus 380-384 reasoning tokens on plain requests and on minimal/low/medium/high effort minimal, low, medium, high, no toggle
glm-4.6 128-543 reasoning tokens for every graded effort value, 0 for effort = "none" (3 of 3) and for reasoning.enabled = false (4 of 4) toggle, as providers/zhipuai has it

gemini-3-5-flash documents its own surface in the 400 it returns: reasoning.enabled = false and effort = "none" both give unsupported_reasoning_effort - "Gemini 3 thinking cannot be disabled. Supported reasoning effort values are minimal, low, medium, and high." - and xhigh gives "... received 'xhigh'." Those four values are the host's own list rather than mine.

One off control per model

reasoning.enabled = false and effort = "none" both suppress reasoning on these routes, so each keeps the toggle and graded values with no none (reasoning tokens in brackets):

  • deepseek-v4-flash - false [0], true [77], high [141], xhigh [183], so toggle + high, xhigh
  • deepseek-v4-pro - false [0], true [240], high [136], xhigh [216], so toggle + high, xhigh
  • deepseek-v4-flash-0731 - false [0], low [81], high [39], max [99], so toggle + low, high, max
  • qwen-3-8-27b - false [no content, 2 of 2], low [244 chars], medium [407], xhigh [215], so toggle + low, medium, xhigh and none dropped

minimax-m2.7 does have a real toggle: plain [252], reasoning.enabled = false no reasoning_content in 4 of 4, true [160]. So it carries toggle with a wire comment rather than the empty list.

budget_tokens

claude-opus-4.5, claude-opus-4.6, claude-sonnet-4.5 and claude-sonnet-4.6 accept thinking = {type: "enabled", budget_tokens: 2048} with 200 and change nothing - they are four of the nine that return no reasoning at all - so the budget is gone. The same check on the three files the review did not flag: qwen3-5-35b-a3b, qwen3-6-35b-a3b and qwen3.6-27b ignore both reasoning.max_tokens = 64 and thinking.budget_tokens = 64, returning about a thousand characters of reasoning either way, so budget_tokens is gone there too while their re-verified toggles stay. No file in this provider carries budget_tokens now.

interleaved

Added wherever the reply carries a side channel, left off where it does not. 33 models return reasoning_content. gemini-3-flash-preview returns reasoning_details with no content. glm-4.7 returns its reasoning in a plain reasoning field, which is not in the schema enum, so it carries interleaved = true. The OpenAI-shaped routes (gpt-5.6-*, gpt-6-astra, gpt-5.4*, gpt-5-mini, gpt-5-nano, gpt-5.5) count reasoning tokens in usage but expose no content, and muse-spark-1.2 and gemini-3.6-flash behave the same way, so none of them carry interleaved.

attachment and modalities

Probed with an image_url part carrying a 1x1 PNG. gemini-3-flash-preview and gemini-3.1-pro-preview answer it (2 of 2 each), so attachment = false came off them - the catalog reports capabilities.vision: false for both, and that is wrong. The other sixteen reject it, either 400 or every upstream route failing, so they keep attachment = false and now also override modalities.input to ["text"] so the two agree. claude-opus-5 is the ragged one: rejected on two of three requests and accepted on one, the same per-request routing variance as everywhere else, so it stays false and its comment says exactly that.

Tiers

271_999 to 272_000 on luna, sol and terra. The catalog reports input_token_price_threshold 271,999 and the band starts one token later, which is what gpt-6-astra and the sync module already use.

One thing the review did not ask about

gpt-5.5-pro cannot be called on this endpoint at all: /v1/chat/completions returns 400 "Pro reasoning mode requires the /v1/responses endpoint" for every request, including a bare "hi", while /v1/responses answers. It now carries [provider] shape = "responses", and its effort list is medium, high, the values that endpoint accepts - low returns 400 and xhigh fails upstream.

Worth knowing for the sync module: the catalog's own capabilities are not dependable in either direction. reasoning reads false for three models that do reason, vision reads false for two that accept images, and endpoint reads /v1/chat/completions for a model that endpoint rejects. That is why the module refuses to write reasoning_options and leaves the capability fields hand-authored.

…routes

claude-fable-5, claude-fable-5.1 and claude-opus-5-fast advertise capabilities.vision
true, but an image_url part is rejected on every attempt (502 or 400, "all available
provider routes failed"), exactly like the other Anthropic routes on this host, so they
get attachment = false and a text-only input modality. All three do return the reasoning
side channel in reasoning_content, so interleaved stays.

gemini-3.6-flash reports usage.completion_tokens_details.reasoning_tokens but the message
carries only content on 8 of 8 probes, so no side channel is declared for it.

muse-spark-1.2 returns its reasoning in reasoning_details on 3 of 3 untruncated probes
(runs cut short by max_tokens carry none), so interleaved.field is set accordingly.
…he sync

A model that reasons on this host but exposes no reasoning controls in the catalog
still needs hand-authored reasoning_options. Throwing a plain Error aborted the whole
run, so a single new model could silence the hourly sync for every other model.

MissingReasoningOptionsError is the shape the runner already understands: it keeps the
local file, records the ID and carries on, so the gap is reported without stopping the
run.
…e reasoner

The old assertion only matched the message text, so a plain Error would have passed it.
It now asserts the error type and the model ID it carries.

A second test drives syncProvider over a temporary models directory holding one
researched and one unresearched reasoner, and checks what the run actually does with
them: the unresearched file is left byte-for-byte alone, nothing is deleted, the other
model still syncs, and the ID is handed to the missing-model issue opener.
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/cheaperinference/models/claude-opus-4-8-fast.toml:4 - Check: Distinct display name for host-specific speed aliases. Why: Both claude-opus-4-8-fast and claude-opus-5-fast point at the non-fast lab bases and omit name, so they inherit identical labels (Claude Opus 4.8 / Claude Opus 5) as the standard routes. Peer hosts disambiguate these aliases (e.g. Vercel/Venice use Claude Opus … Fast). Action: Add distinct name overrides on both fast files (and any other host-only alias that would otherwise collide with the base display name).
  • [high] [possible mistake] providers/cheaperinference/models/claude-opus-4.5.toml:9 - Check: Relay reasoning / reasoning_options vs lab + same-surface peers. Why: These routes set reasoning = false even though lab metadata is reasoning = true, first-party Anthropic exposes effort/budget controls, and OpenRouter same-surface peers expose a reasoning toggle. The files themselves note the catalog still reports capabilities.reasoning true. Marking them non-reasoning hides controls clients expect on an OpenAI-compatible Claude relay. Same pattern on claude-opus-4.6, claude-sonnet-4.5, claude-sonnet-4.6, and claude-opus-4.7. Action: Re-verify with the same request shapes peers use (and any thinking-block / reasoning_content path this gateway documents). If reasoning is reachable, restore reasoning = true plus host-accurate reasoning_options (and drop reasoning = false). If it truly never reasons on every upstream route, keep reasoning = false and cite that conclusive host evidence in the leading comment.
  • [high] [possible mistake] providers/cheaperinference/models/gemini-2.5-flash.toml:6 - Check: Relay reasoning capability for known Gemini reasoners. Why: Lab, first-party Google, and OpenRouter all treat gemini-2.5-flash as a reasoner with caller controls (toggle / budget or effort). This PR forces reasoning = false. The same mismatch applies to gemini-3.1-flash-lite and claude-haiku-4.5 (lab + OpenRouter reason; this host disables reasoning). Action: Confirm on-wire that no effort/toggle/budget form yields reasoning tokens or a side channel on this host; if any form works, restore reasoning + matching reasoning_options. If the catalog’s capabilities.reasoning false is the only signal and probes are incomplete, do not author reasoning = false from that alone.
  • [medium] [violation] packages/core/src/sync/providers/cheaperinference.ts:169 - Check: Sync must preserve hand-authored provider-only fields. Why: buildCheaperInferenceModel only rebuilds cost/limit from the API, then spreads the full resolved existing model into factorBaseModel. That is fine for fields present on disk today, but hourly rewrites will still drop anything the serializer omits when equality checks change, and the module never explicitly re-attaches provider-only keys the way peer syncs do (interleaved, provider, attachment, modalities, status). After the first successful sync of probe-authored side channels / text-only modalities / provider.shape = "responses", a later run that re-factors against lab defaults can silently strip those overrides. Action: Explicitly pass through (and test) hand-authored provider-only fields—at least interleaved, provider, attachment, modalities, reasoning, and reasoning_options—so pricing sync cannot erase live-probed host behavior.
  • [medium] [possible mistake] providers/cheaperinference/models/qwen-3-8-max.toml:8 - Check: Relay baseline for Qwen3.8 Max reasoning controls. Why: Lab/Alibaba author toggle + effort low|medium|xhigh + budget_tokens. This host uses reasoning_options = [] (always-on, no control). That is valid only with affirmative proof that every off/effort/budget form is a no-op on this path; lab and other relays disagree. Action: Keep [] only if re-probes still show always-on with no effective control; otherwise restore the intersection of lab/peer controls this gateway actually forwards (toggle and/or effort), with wire comments.

@aiapienthusiast

Copy link
Copy Markdown
Author

All four items are addressed on the branch.

1. A single unresearched reasoner aborted the sync. buildCheaperInferenceModel now throws MissingReasoningOptionsError instead of a bare Error, so the runner records the ID, keeps the local file and carries on — one new reasoning model can no longer stop the run for all the others. The old test only matched the message text, so a plain Error would still have passed it; it now asserts the error type and the modelId it carries. A second test drives syncProvider over a temporary models directory holding one researched and one unresearched reasoner, and checks what the run does with them: nothing deleted, the unresearched file byte-for-byte unchanged, the other model synced, and the ID handed to openMissingModelIssues.

2-4. Probed against the host on 2026-09-16, same key and catalog version as the pricing lines:

id probe result
gemini-3.6-flash 8 reasoning requests usage.completion_tokens_details.reasoning_tokens 235-385 every time, message keys role/content only. No side channel to declare, so no interleaved; the finding is recorded as a leading comment instead.
muse-spark-1.2 3 untruncated reasoning requests reasoning_details on the message 3/3 (runs cut short by max_tokens carry none), so [interleaved] field = "reasoning_details".
claude-fable-5, claude-fable-5.1, claude-opus-5-fast an image_url part, 2 attempts each rejected every time (502, 400, 400 - "all available provider routes failed"), exactly like the other Anthropic routes here, although the catalog reports capabilities.vision true. Hence attachment = false and [modalities] input = ["text"].

Those three do return reasoning content, so interleaved stays on them: reasoning_content on 5 of 5 later probes, with claude-fable-5.1 needing a prompt long enough that the answer is not truncated before the field appears.

Every one of these files carries the probe counts as a leading comment, so the next person reading it can see what was measured rather than what the catalog claims.

The earlier image-input probe used a 1x1 PNG. Upstreams treat that as junk: routes that handle a
normal image returned 400 or 502 "all available provider routes failed", and some that do accept images
answered "White" for a red pixel. Every attachment and modalities value derived from that probe was
wrong, in both directions.

Re-probed with a 32x32 solid-colour PNG as a data: URI, four colours per model, max_tokens high enough
that a reasoning model still answers, and a text-only control on every route that errored, so "no image
input" is separated from "route down". A route counts as having image input only when it names the
colour; several accept the request and then answer NOIMAGE or guess.

Image input works on 36 of the 59 chat routes reachable on /v1/chat/completions, plus gpt-5.5-pro on the
/v1/responses layer it requires. Each file states what was measured. Two notes:

- deepseek-v4-flash-0731 reads images here although its base model is text-only (10 of 10 probes), so it
  carries an explicit attachment and modalities override rather than inheriting.
- A remote https image URL is rejected by every route tested; only data: URIs work.

Rates re-read at the same time (pricing_version sha256:6d2520b9, 2026-09-17T07:00:28Z): deepseek-v4.1-flash
doubled, glm-5.3-flash and muse-spark-1.2 fell, gpt-5.4-nano rose. The other rates are unchanged.
Same 32x32 data: URI probe as the sibling routes: 4 of 4 colours named correctly, so this route keeps
image input. Rates re-read at the same catalogue version.
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/cheaperinference/models/glm-4.5.toml:5 - Check: After base_model, provider files must be override-only (no duplicated identical fields). Why: Several files restate attachment = false and/or a text-only [modalities] block that already match the lab entry, which violates the override-only rule and will keep being rewritten by sync. Action: Drop identical attachment / [modalities] overrides on text-only bases: glm-4.5, glm-4.5-air, glm-4.6, glm-4.7, glm-5, glm-5.1, glm-5.2, glm-5.3, gpt-oss-120b, minimax-m2.7, deepseek-v4-flash, deepseek-v4-pro, and deepseek-v4-pro-0813. Keep those fields only where they actually differ from base_model (e.g. glm-5.3-flash, vision models with real text-only host limits).
  • [medium] [violation] providers/cheaperinference/models/claude-opus-4.5.toml:1 - Check: Leading comments must not contradict the authored fields. Why: Patch 15 verifies image input and removes attachment = false, but older “No image input … capabilities.vision false” lines remain in the same header, so the file documents opposite host behaviour. Action: Delete the stale no-image comments on claude-opus-4.5, claude-opus-4.6, claude-opus-4.7, claude-sonnet-4.5, and claude-sonnet-4.6 so the header matches the final attachment/modalities inheritance.
  • [medium] [violation] providers/cheaperinference/models/qwen-3-8-max.toml:1 - Check: Leading comments must not contradict the authored fields. Why: These files now inherit image input (attachment restored), but still carry the old “No image input … vision false” comments next to the new “Image input verified” notes. Action: Remove the stale no-image comments from qwen-3-8-max.toml and qwen3-5-35b-a3b.toml.
  • [low] [possible mistake] providers/cheaperinference/models/claude-opus-4-8-fast.toml:1 - Check: Leading comments should be a single consistent evidence block. Why: The header stacks two separate “No image input” notes (2026-09-17 and 2026-09-16) for the same claim. Action: Collapse to one probe note so sync-preserved headers stay readable.

@aiapienthusiast

Copy link
Copy Markdown
Author

Correction to my own comment above: the image-input part of it was wrong, and the branch now carries the fix.

That probe used a 1x1 PNG. Upstreams treat a 1x1 image as junk, so routes that handle a normal image came back 400 or 502 "all available provider routes failed", and some that do accept images answered "White" for a red pixel. Every attachment and modalities value I derived from it was unreliable - in both directions.

Re-probed today with a 32x32 solid-colour PNG as a data: URI, four colours per route (blue, green, yellow, purple), max_tokens high enough that a reasoning model still answers after thinking, and a text-only control on every route that errored, so "no image input" is separated from "route down". A route counts as having image input only when it names the colour: several accept the request and then answer NOIMAGE or guess.

Result: image input works on 36 of the 59 routes reachable on /v1/chat/completions, plus gpt-5.5-pro on the /v1/responses layer it requires. Concretely for the three IDs in item 4 - claude-fable-5, claude-fable-5.1 and claude-opus-5-fast all read the image on 4 of 4 colours, so the attachment = false overrides I added are gone again. Where the flag now stays false, the file says which of the two things happened: the part is rejected outright (with the status and the text-only control), or the request is accepted and the model answers NOIMAGE.

Two findings worth having in the repo:

  • deepseek-v4-flash-0731 reads images on this host although its base model is text-only (10 of 10 probes across four colours), so it carries an explicit attachment/modalities override rather than inheriting.
  • A remote https:// image URL is rejected by every route tested; only data: URIs get through. So a client that passes image URLs through will see failures that have nothing to do with the model.

Rates were re-read in the same pass (pricing_version sha256:6d2520b9, 2026-09-17T07:00:28Z): deepseek-v4.1-flash doubled, glm-5.3-flash and muse-spark-1.2 fell, gpt-5.4-nano rose; the rest are unchanged. bun run validate passes and the provider tests are green.

…be notes

Override-only rule: 13 text-only entries restated attachment = false and a
[modalities] block identical to the lab entry, and 10 more restated
modalities.output. Those lines are gone; base_model merges deeply, so the
generated output is byte-identical (checked with bun run validate before and
after).

Headers: the 2026-09-16 no-image note is removed from the 8 files where the
2026-09-17 probe supersedes it - 7 that now verify image input, and
claude-opus-4-8-fast, where it repeated the newer no-image note.

bun run validate exits 0; bun test packages/core is 305 pass / 3 fail, the same
3 failures as on the branch without this change.
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [possible mistake] providers/cheaperinference/models/claude-opus-4.5.toml:1 - Check: Host reasoning must reflect this API’s real behavior; reasoning = false is only valid when the route never reasons. Why: These files set reasoning = false while the lab entries are reasoners and the PR’s own headers note the gateway catalog still reports capabilities.reasoning true for opus/sonnet 4.5–4.6. Same-surface OpenAI-compatible peers (e.g. OpenRouter) expose real controls for these IDs. A false negative probe would strip reasoning from the catalog for flagship models. Action: Re-probe with the peer wire forms that work elsewhere (reasoning.enabled, effort, and any Claude extended-thinking field this path actually forwards). If reasoning content or reasoning tokens appear under any form, drop reasoning = false and author the working reasoning_options (or [] only if always-on with no control). Same review for claude-opus-4.6.toml, claude-sonnet-4.5.toml, and claude-sonnet-4.6.toml.
  • [medium] [possible mistake] providers/cheaperinference/models/gemini-2.5-flash.toml:1 - Check: Do not mark a lab reasoner reasoning = false on a relay without ruling out the host’s real control surface. Why: Lab/first-party treat Gemini 2.5 Flash, Gemini 3.1 Flash Lite, Claude Haiku 4.5, and Claude Opus 4.7 as reasoners (Google: toggle + budget_tokens; Anthropic Opus 4.7: effort ladder; Haiku 4.5: budget_tokens). OpenRouter-style peers also expose controls for several of these. Catalog capabilities.reasoning false alone is not enough if the OpenAI-compat path still forwards thinking/effort. Action: Re-test with first-party/peer request shapes (thinking_budget / reasoning.enabled / effort). Keep reasoning = false only if every form returns neither reasoning content nor reasoning-token usage; otherwise author the controls that work. Applies to gemini-3.1-flash-lite.toml, claude-haiku-4.5.toml, and claude-opus-4.7.toml.
  • [low] [possible mistake] providers/cheaperinference/models/claude-sonnet-5.toml:1 - Check: Relay reasoning_options should match controls this host actually forwards when the lab exposes them. Why: First-party Claude Sonnet 5 is toggle + effort low|medium|high|xhigh|max; this file is effort-only. The PR says reasoning.enabled had no effect here, which can be correct, but leaves callers without the lab off-switch if a different wire path works. Action: Confirm no on/off field works (including lab thinking.type if forwarded). If a toggle works, add toggle plus a leading wire comment; if only effort works, keep as-is.

…rwards

The review is right: reasoning = false was wrong for six of the eight ids that
carried it. Re-probed each id with six wire forms (plain, top-level
reasoning_effort, reasoning.enabled, reasoning.effort, thinking.type with
budget_tokens, thinking_budget), three samples per cell, scoring
usage.completion_tokens_details.reasoning_tokens and message.reasoning_content.

- claude-sonnet-4.5: toggle, thinking.type = enabled|disabled (205-308 reasoning
  tokens on, none off)
- claude-sonnet-4.6: toggle plus effort medium|high|max (53 / 110-153 / 301-320)
- claude-opus-4.6: toggle plus effort high|max (218-261 / 636-650 characters)
- claude-opus-4.5 and claude-haiku-4.5: they reason, but no control could be
  reproduced - reasoning_options = []
- gemini-3.1-flash-lite: effort minimal|low|medium|high, and the host itself
  rejects reasoning_effort = "none" with "Gemini 3 thinking cannot be disabled.
  Supported reasoning effort values are minimal, low, medium, and high."
- claude-opus-4.7 and gemini-2.5-flash keep reasoning = false: 18 requests each,
  no reasoning under any form

The same host error also fixes three ladders that were authored from lab
convention: gemini-3.1-pro-preview and gemini-3.7-flash were missing "minimal",
and gemini-3.6-flash now carries the wire comment. claude-sonnet-5 drops to
effort ["max"], the only level that measurably reasons there.

bun run validate exits 0; bun test packages/core is 305 pass / 3 fail, the same 3
failures as on the branch without this change.
@aiapienthusiast

Copy link
Copy Markdown
Author

Both review rounds are addressed, in 83d1fa5 and 838cd44.

Override-only and stale headers (83d1fa5)

13 text-only entries restated attachment = false and a [modalities] block identical to the lab entry (glm-4.5, glm-4.5-air, glm-4.6, glm-4.7, glm-5, glm-5.1, glm-5.2, glm-5.3, gpt-oss-120b, minimax-m2.7, deepseek-v4-flash, deepseek-v4-pro, deepseek-v4-pro-0813). I also found 10 more that restated only modalities.output while their input differs; mergeBaseModel merges deeply, so the single line is dropped and output is inherited. 30 files, 91 lines removed, nothing added, and bun run validate gives byte-identical output for the whole provider before and after.

The 2026-09-16 no-image note is gone from the 8 files where the 2026-09-17 probe supersedes it, including the stacked pair on claude-opus-4-8-fast.

Reasoning controls (838cd44)

The high-severity finding is correct, and reasoning = false was wrong on six of the eight ids that carried it. Method: six wire forms per id — plain, top-level reasoning_effort, reasoning.enabled, reasoning.effort, thinking.type with budget_tokens, and Google's thinking_budget — three samples per cell, scored on usage.completion_tokens_details.reasoning_tokens and message.reasoning_content.

id before now evidence
claude-sonnet-4.5 reasoning = false toggle thinking.type = "enabled" 205-308 reasoning tokens on 5 of 5, "disabled" none on 2 of 2
claude-sonnet-4.6 reasoning = false toggle + effort medium/high/max 53 / 110-153 / 301-320 tokens; low and no field 0; reasoning.enabled = false 0
claude-opus-4.6 reasoning = false toggle + effort high/max 218-261 / 636-650 characters; low/medium at the 75-76 baseline; enabled = false 0
claude-opus-4.5 reasoning = false reasons, reasoning_options = [] plain carried 1007-1144 characters on 3 of 3 and thinking.type = "disabled" did not suppress it
claude-haiku-4.5 reasoning = false reasons, reasoning_options = [] 2 of 20 requests reasoned (241 tokens once, 964 characters once), the other 18 did not
gemini-3.1-flash-lite reasoning = false effort minimal/low/medium/high see the host error below
claude-opus-4.7 reasoning = false unchanged 18 requests, no reasoning under any form
gemini-2.5-flash reasoning = false unchanged 18 requests, no reasoning under any form, including thinking_budget

The host answers the Gemini 3 question itself. reasoning_effort = "none" returns 400:

unsupported_reasoning_effort: Gemini 3 thinking cannot be disabled. Supported reasoning effort values are minimal, low, medium, and high.

That applies to every Gemini 3 id here (gemini-3-5-flash, gemini-3-flash-preview, gemini-3.1-flash-lite, gemini-3.1-pro-preview, gemini-3.6-flash, gemini-3.7-flash), so gemini-3.1-pro-preview and gemini-3.7-flash gained the minimal level they were missing, and the wire comment now quotes the host instead of a lab convention.

On the low-severity item: claude-sonnet-5 drops from five effort levels to ["max"]. Only max measurably reasons there (343 and 1199 tokens); no field, low, medium, high, xhigh, reasoning.enabled = true and thinking.type = "enabled" all returned 0 on 2 of 2. That route accepts an invalid value instead of rejecting it, so the level list comes from measurement rather than an error message.

One caveat worth recording, because it explains the earlier wrong values: the gateway picks an upstream route per request (the reply's provider member came back as "Anthropic" on some calls and "Claude Platform on AWS" on others for the same id), and reasoning behaviour follows the route. That is why claude-opus-4.5 and claude-haiku-4.5 are authored as reasoners with no caller control rather than with a control that only sometimes fires. Each file's header carries its own sample counts.

bun run validate exits 0; bun test packages/core is 305 pass / 3 fail — the same three failures the branch has without these changes.

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/cheaperinference/models/claude-haiku-4.5.toml:9 - Check: reasoning_options = [] means the model reasons with no caller control. Why: The authored probe says only 2 of 20 requests produced reasoning and the other 18 returned none across every wire form, so this is not an always-on reasoner. Publishing [] (with lab reasoning = true) tells clients the route always reasons and cannot be controlled, which misstates this host. Action: Do not use [] here. Prefer reasoning = false if non-reasoning is the stable host behavior, or author only controls that reproducibly change reasoning; drop the empty options list either way.
  • [medium] [possible mistake] providers/cheaperinference/models/claude-opus-4.5.toml:11 - Check: Empty reasoning_options on a multi-upstream relay. Why: The header says plain requests can return reasoning_content on one upstream while an earlier route for the same ID returned none, and thinking.type = disabled did not suppress reasoning. [] claims stable always-on thinking with no control; route-dependent on/off is a different capability surface. Action: Reconcile with a single host truth: if the gateway can leave reasoning off by default on some routes, do not use []; if it is always-on whenever this ID is served, keep [] and drop the contradictory “earlier route returned none” claim from the header so the catalog is not self-conflicting.
  • [medium] [possible mistake] providers/cheaperinference/models/claude-opus-4.7.toml:10 - Check: reasoning = false on a lab/first-party reasoner. Why: models/anthropic/claude-opus-4-7 and providers/anthropic/models/claude-opus-4-7 are reasoning = true with effort controls. Overriding that to false is high-impact; the PR cites 18 empty probes and a gateway capabilities.reasoning false flag, but that conflicts with the lab surface and could be a broken or non-thinking upstream mix rather than a true capability. Action: Re-verify on a healthy text-only path that this ID never emits reasoning tokens/content under the same controls peers use; if any upstream reasons, restore reasoning = true and author the real host controls (or [] only if always-on with no control).
  • [medium] [possible mistake] providers/cheaperinference/models/gemini-2.5-flash.toml:11 - Check: reasoning = false on Gemini 2.5 Flash. Why: Lab and first-party Google entries treat this as a reasoner (toggle + budget_tokens on providers/google/models/gemini-2.5-flash.toml). Forcing reasoning = false on the relay is a large capability downgrade relative to the model identity. Action: Confirm the gateway never bills/returns reasoning for this ID under Google-style thinking controls; if it does on any route, restore reasoning and author the host-visible options instead of a blanket false.

claude-haiku-4.5: 21 more requests across all seven wire forms returned no reasoning at all, so
the empty options list goes and the id is reasoning = false. The two early reasoning replies are kept in
the header as an unreproducible route artefact.

claude-opus-4.5: a 34-request matrix separates the routes. On the route that answers as
anthropic/claude-opus-4-5, plain requests, reasoning_effort = "none" and reasoning.enabled = false all
return 0 reasoning tokens, while "low" returns 32, "medium" 32-105 and "high" 242-246, and
thinking.type = "enabled" returns 276-313. That is a toggle plus a graded effort ladder, so those are
authored and the empty list and the contradictory header claim are gone. The interleaved field goes too:
that route reports reasoning in usage and returns no reasoning_content.

claude-opus-4.7: 21 more requests, every one answered by Claude Platform on AWS, all with a reasoning
token count of 0. reasoning = false stands, on one route rather than a fan-out.

gemini-2.5-flash: 36 more requests, every one answered by Google AI Studio, all zero - including Google's
own controls in four shapes, among them
extra_body.google.thinking_config = { thinking_budget = 1024, include_thoughts = true }.
reasoning = false stands.

bun run validate passes; the generated JSON changes only for claude-haiku-4.5 and claude-opus-4.5.
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/cheaperinference/models/claude-opus-4.5.toml:17 - Check: toggle must not be paired with effort values that already include none; every toggle needs a leading wire-path comment. Why: Final options are toggle plus effort = ["none", "low", "medium", "high"] with no # Toggle: … header. That breaks the reasoning-options rules (none already means off) and leaves clients without a documented on/off field even though the file header cites both reasoning.enabled and reasoning_effort. Action: Pick one shape: either drop toggle and keep effort with none|low|medium|high (and document the effort wire path), or drop none and keep toggle + graded effort with a leading # Toggle: … comment naming the exact field this host forwards.

Picking the second shape the reviewer offered.

reasoning.enabled is the on/off field, and it is the one control that survives the gateway's fan-out:
true reasoned on 9 of 9 requests (193-237 reasoning tokens) and false returned 0 on 12 of 12, on both
routes the id is served from. Requests with no reasoning field returned 0 on 8 of 9.

reasoning_effort is graded but only on the route that answers as anthropic/claude-opus-4-5: "low" 32-33
(3 of 3), "medium" 32-105 (4 of 4), "high" 230-255 (5 of 5). The Amazon Bedrock route returns 0 for
every effort value. "none" is removed from the list so it no longer overlaps the toggle, and the two
wire paths are named in leading Toggle: / Effort: comments.

bun run validate passes; the generated JSON changes only for claude-opus-4.5.
@aiapienthusiast

Copy link
Copy Markdown
Author

Two rounds answered, in 6f74049 and c8414a7.

Round 5 (6f74049)

claude-haiku-4.5 — you were right that [] was wrong. 21 fresh requests — seven wire forms (plain, top-level reasoning_effort, reasoning.enabled, reasoning.effort, reasoning.max_tokens, thinking.type, thinking_budget) × 3 samples — returned no reasoning at all, so 39 of 41 across both rounds show none. The id is now reasoning = false; the empty options list and the interleaved field are gone, and the two early reasoning replies stay in the header as an artefact of a route the caller cannot select.

claude-opus-4.5 — the header really did contradict itself. Conditioning on the upstream route resolved it, and round 6 below settles the shape.

claude-opus-4.7 — re-verified on a healthy route: 21 more requests, every one answered by Claude Platform on AWS, reasoning token count 0 throughout. reasoning = false now rests on one route rather than a fan-out.

gemini-2.5-flash — re-verified with Google's own controls in four shapes: extra_body.google.thinking_config = { thinking_budget: 1024, include_thoughts: true }, google.thinking_config, bare thinking_config, and thinking_budget with include_thoughts. 36 more requests, all answered by Google AI Studio, all zero. reasoning = false.

Round 6 (c8414a7)

Took your second option for claude-opus-4.5: keep the toggle, drop none, name the wire paths.

A 30-request follow-up shows reasoning.enabled is the control that survives the fan-out — true reasoned on 9 of 9 requests (193–237 reasoning tokens) and false returned 0 on 12 of 12, on both routes this id is served from. Requests with no reasoning field returned 0 on 8 of 9.

reasoning_effort is graded, but only on the route that answers as anthropic/claude-opus-4-5: "low" 32–33 (3 of 3), "medium" 32–105 (4 of 4), "high" 230–255 (5 of 5). The route that answers as claude-opus-4-5 through Amazon Bedrock returns 0 for every effort value.

So the file now reads:

# Toggle: reasoning.enabled = true|false
# Effort: reasoning_effort = low|medium|high

with effort = ["low", "medium", "high"] — same format as claude-opus-4.6.

bun run validate passes on both commits; the generated JSON changes only for claude-haiku-4.5 and claude-opus-4.5.

@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Sep 17, 2026
@aiapienthusiast

This comment was marked as duplicate.

Re-read GET /v1/models: the pricing_version advanced from sha256:6d2520b9 to sha256:42cddd4d.
Of the 60 Cheaper Inference entries, 57 are byte-for-byte unchanged and three moved, all through the
discount rather than the model maker's list price:

- deepseek-v4-flash: discount 45.09% -> 56.62%, so $0.071388/$0.142777 becomes $0.056398/$0.112796
- deepseek-v4.1-flash: 30.00% -> 59.72%, so $0.21/$0.84 becomes $0.120853/$0.483412
- muse-spark-1.2: 30.00% -> 15.00%, so $0.875/$2.975 becomes $1.0625/$3.6125

The Rates: header on those three files now cites the new pricing_version and timestamp; the other 57
keep theirs, because those figures were read at that version and have not changed.

bun run validate passes; the generated JSON differs only for these three ids.
@github-actions github-actions Bot removed the reviewer: ready Automated review found no actionable items label Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant